var logger = Logger.getLogger();

var BishopMoveStrategy = {
	canMove : 
		function(_src, _dst){
			return _src.i - _dst.i == _src.j - _dst.j
				|| _src.i - _dst.i == -( _src.j - _dst.j );
		} 
}
var RookMoveStrategy = {
	canMove : 
		function(_src, _dst){
			return _src.i == _dst.i || _src.j == _dst.j;
		} 
}
var KnightMoveStrategy = {
	canMove : 
		function(_src, _dst){
			var disX = _src.i - _dst.i;
			disX = disX<0 ? -disX : disX;
			var disY = _src.j - _dst.j;
			disY = disY<0 ? -disY : disY;
			return disX*disY == 2 && disX + disY == 3;
		} 
}
var KingMoveStrategy = {
	canMove : 
		function(_src, _dst, _game){
			var disX = _src.i - _dst.i;
			disX = disX<0 ? -disX : disX;
			var disY = _src.j - _dst.j;
			disY = disY<0 ? -disY : disY;
			var r = disX<2&&disY<2;
			if(!r){
				if(disX<2 && disY<2){
					logger.debug("normal move");
					r = true;
				}
				else {
					r = !_game.isKingMoved(this.color); //initial place
					r = r && _src.i == _dst.i ;
					r = r && (_dst.j==0||_dst.j==7);
					
				}
			}
			return r;
		} 
}
var QueenMoveStrategy = {
	canMove : function(_src, _dst){
			return RookMoveStrategy.canMove(_src, _dst) ||
				BishopMoveStrategy.canMove(_src, _dst);
		} 
}
var PawnMoveStrategy = {
	canMove : 
		function(_src, _dst , _game){
			var r = false;
			logger.debug("try to move from ("+_src.i+","+_src.j+") to ("+_dst.i+","+_dst.j+")");
			var isHomeUp = (_game.isWhiteUp) == (this.color=="w")
			var step = _dst.i-_src.i;
			step = isHomeUp ? step : -step;
			logger.debug("try to move "+step+" steps");
			var dist = _game.at(_dst);
			var hDis = _dst.j - _src.j;
			if(step==2 && hDis==0 && !dist){ // move 2 steps, must be at initial place.
				if(_src.i == (isHomeUp ? 1:6)){
					r = true;
					logger.debug("home loooooooog jump!");
				}
			} 
			else if( step==1){//so move 1 step up
				if( hDis==0 ){
					logger.debug("normal move. h move = "+hDis);
					r = true;
				}
				else if( hDis==1 || hDis==-1 ){ 
					if(dist){ //cross eat? note, same-color-eat check has been done by super method
						r = true;
						logger.debug("cross eat");
					}
					else { 
						if(_game.isPassantPawn(_dst)){
							r = true;
							logger.debug("en passant");
						}
					}
				} 
			}	
			logger.debug("Bin.canMove return " + r);		
			return r;
		} 
}

var GameControl = {
	getMoveStrategy : function(_for){
		var map = [
			[ Rook,RookMoveStrategy ],
			[ Knight, KnightMoveStrategy ],
			[ Bishop, BishopMoveStrategy ],
			[ Queen, QueenMoveStrategy ], 
			[ King, KingMoveStrategy ] 
		];
		for(var i=0; i<map.length; i++){
			if(_for instanceof map[0])
				return map[1];
		}
	},
	pathOccupied : function(_src, _dst, _game){
		//check if there is any piece on the path
		var start = {
			i: Math.min(_src.i,  _dst.i),
			j: Math.min(_src.j,  _dst.j)
		};
		var end = {
			i: Math.max(_src.i,  _dst.i),
			j: Math.max(_src.j,  _dst.j)
		};
		
		var iStep = -1, jStep = -1;
		if(iEnd - iStart==0) {
			iStep = 0;
			jStep = 1;
		}
		else if(jEnd - jStart==0) {
			iStep = 1;
			jStep = 0;
		}	
		else if(iEnd - iStart==jEnd - jStart) {
			iStep = jStep = 1;
		}
		else {
			return false;
		}	
		do{
			start.i += iStep;
			start.j += jStep;
			if(_game.at(start))
				return true;
		}while(start.i<end.i&&start.j<end.j);
		return false;		
	}
	canMoveTo : function(_src, _dst, _game){
		var atSrc = _game.at(_src);
		var atDst = _game.at(_dst);
		if(!atSrc) {
			logger.debug("GameControl: move with no piece is not allowed");
			return false;
		} 
		if(_src.i==_dst.i && _src.j==_dst.j) {
			logger.debug("GameControl: no move is not allowed");
			return false; 
		}
		if(atDst && atDst.color==atSrc.color) {
			logger.debug("GameControl: capture same color is not allowed");
			return false; 
		}
		if(this.pathOccupied(_src, _dst, _game)){
			logger.debug("GameControl: move path is occupied by other piece");
			return false;
		} 
		moveStrategy = this.getMoveStrategy();		
		var r = moveStrategy.canMove(_src, _dst , _game);
		logger.debug("GameControl: Piece specified ajudgment says " +(r?"yes":"no")+" to this movement");
	}
}
